#! /bin/bash

if [ -L "${0}" ]; then
    VMS_HOME=$(
        cd -P $(dirname $(readlink "${0}"))
        pwd
    )
else
    VMS_HOME=$(
        cd -P $(dirname "${0}")
        pwd
    )
fi

. "${VMS_HOME}"/conf/vms.properties
. "${VMS_HOME}"/conf/module.properties
. "${VMS_HOME}"/conf/plugins
his_file="${VMS_HOME}"/log/vms.history

#########################################
############### functions ###############
#########################################

# disable exit
exit() {
    echo -e "\e[31mexit is disabled, please use return statement.\e[0m"
}

help() {
    if [ $# -lt 1 ]; then
        version
        cat "${VMS_HOME}"/man/vms.man
    else
        cat "${VMS_HOME}"/man/"${1}".man
    fi
}

version() {
    echo -e "Vertical Management System \e[35m${Version}\e[0m, Powered by \e[33m${Author}\e[0m"
}

info() {
    version
    echo -e "// TODO shows infos of vms, modules, system, etc."
}

status() {
    # -s silent ==> ignore echo
    [[ "${1}" == "-s" ]] && local silent_flag="yes" && shift
    local res
    local s_code
    res=$(status_"${1}")
    s_code=$?
    [ "${silent_flag}" ] || echo "${res}"
    return "${s_code}"
}

start() {
    verify_module "$@" || return 1
    local start_module
    for start_module in "${StartOrder[@]}"; do
        is_in "${start_module}" "$@" || continue
        is_in "${start_module}" "${!Dependencies[@]}" && start ${Dependencies[${start_module}]}
        echo "============== starting ${start_module}... =============="
        status -s "${start_module}" && echo start_"${start_module}" || echo "${start_module} is already running."
    done
}

sync() {
    [ $# -lt 1 ] && echo -e "Parameter missing!" && return 1
    get_hosts
    for host in "${hosts[@]}"; do
        echo "======= syncing files to ${host}... ======="
        for file in "$@"; do
            if [ -e "${file}" ]; then
                pdir=$(
                    cd -P $(dirname ${file})
                    pwd
                )
                fname=$(basename "${file}")
                ssh "${User}"@"${host}" "mkdir -p ${pdir}"
                rsync -av "${pdir}"/"${fname}" "${User}"@"${host}":"${pdir}"
            else
                echo "-vms: ${file}: No such file or directory!"
            fi
        done
    done
}

update() {
    for seg in "$@"; do
        local var="${seg%%=*}"
        [ "${!var}" ] && eval "${seg}" || echo "${var} is not assigned!"
    done
}

up() {
    update "$@"
}

mrun() {
    [ $# -lt 1 ] && echo -e "Parameter missing!" && return 1
    get_hosts
    for host in "${hosts[@]}"; do
        echo "======= running command on ${host}... ======="
        ssh "${User}"@"${host}" "$@"
    done
}

m() {
    mrun "$@"
}

history() {

    if [ $# -lt 1 ]; then
        cat -n "${his_file}"
        echo -e "\e[33mNote: Navigation key viewing history is currently not supported.\e[0m"
        return 0
    fi

    his_paras=$(getopt -o +cw -n "${FUNCNAME[0]}" -- "$@")
    [ $? -ne 0 ] && return 1
    eval set -- "${his_paras}"
    while true; do
        case "${1}" in
        -c)
            shift
            echo -n "" >"${his_file}"
            return 0
            ;;
        -w)
            shift
            history_rows=$(wc -l <"${his_file}")
            of_rows=$((history_rows - HistoryMax))
            [ "${of_rows}" -gt 0 ] && sed -i "1,${of_rows}d" "${his_file}"
            return 0
            ;;
        --)
            shift
            ;;
        *)
            [[ "${1}" == *[!0-9]* ]] && echo -e "\e[31m${1} is not a NUMBER!\e[0m" && return 2
            echo $(sed -n "${1},${1}p" "${his_file}")
            do_vms $(sed -n "${1},${1}p" "${his_file}")
            return 0
            ;;
        esac
    done
}

his() {
    history "$@"
}

:() {
    cat -n "${his_file}" | grep "$*"
}

!!() {
    history $[$(wc -l < "${his_file}") - 1]
}

do_vms() {
    echo "$@" >>"${his_file}"
    eval set -- "$@"
    vms_cmd="${1}"
    [[ "${vms_cmd}" == "do_vms" ]] && echo -e "\e[31mBad Command!\e[0m" && return -1
    [[ "${vms_cmd}" == "exit" ]] && history -w && unset -f exit && exit
    if [ $(type -t "${vms_cmd}") ]; then
        shift
        ${vms_cmd} "$@"
    else
        echo -e "\e[31m${vms_cmd}: Command Not Found!\e[0m"
    fi
}

#########################################
############### Main body ###############
#########################################
version
echo

while true; do
    wd=$(pwd)
    read -ep $'\e[35m'"[vms-cli ${wd}]# "$'\e[0m' cmd
    [ -z "${cmd}" ] && continue
    do_vms "${cmd}"
done
